package team2.gbike.map;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import team2.gbike.R;
import team2.gbike.location.GPSStore;
import team2.gbike.main.GBike;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;
import bas.gps_fiets.Direction;
import bas.gps_fiets.RouteSelector;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.jsambells.directions.ParserAbstract.Mode;
import com.jsambells.directions.RouteAbstract;
import com.jsambells.directions.RouteAbstract.RoutePathSmoothness;
import com.jsambells.directions.google.DirectionsAPI;
import com.jsambells.directions.google.DirectionsAPIRoute;

public class AndroidGoogleMapsActivity extends MapActivity implements
		com.jsambells.directions.ParserAbstract.IDirectionsListener {

	Button bSend;

	public MapView mapView;
	HashMap<String, GeoPoint> locationOfPlaces;
	HashMap<GeoPoint, String> locationInverse;
	HashMap<String, Drawable> iconsOfPlaces;
	ArrayList<String> selectedPlaces;
	//ArrayList<String> placesInOrder;
	
	private AddItemizedOverlay myLocationOverlay = null;
	public static boolean isLocationAvaliable = false;
	public static boolean showLocationToast = false;
	public static boolean routeNeedsRefresh = false;
	private static boolean showedLocationToast = false;

	private GeoPoint lastDestination= null;
	private GeoPoint nextDestination= null;

	public static Location gpsLocation;
	private static int currentProgress = 0;	

	private double getDistanceBetween2GeoPoints(GeoPoint pointA, GeoPoint pointB){
		
		if(pointA != null && pointB !=null){
		Location locationA = new Location("point A");

		locationA.setLatitude(pointA.getLatitudeE6() / 1E6);
		locationA.setLongitude(pointA.getLongitudeE6() / 1E6);

		Location locationB = new Location("point B");

		locationB.setLatitude(pointB.getLatitudeE6() / 1E6);
		locationB.setLongitude(pointB.getLongitudeE6() / 1E6);

	
		return (Math.abs(locationA.distanceTo(locationB)));
		}
		return 1000;
	}
	
	public void step(){
		char directionOrders[] = {'q','w','e','r','t'};
		Direction newDirection = new Direction();
		GeoPoint myLocation = new GeoPoint(
				(int) (gpsLocation.getLatitude() * 1E6),
				(int) (gpsLocation.getLongitude() * 1E6));
		int progress=0;
		double distanceDone =getDistanceBetween2GeoPoints(myLocation, lastDestination)
				,distanceTotal = getDistanceBetween2GeoPoints(lastDestination, nextDestination)
				,distancePending = getDistanceBetween2GeoPoints(myLocation, nextDestination);
		
		if(distancePending<50){
			if(distancePending<12){
				if(!selectedPlaces.isEmpty()){
					selectedPlaces.remove(0);
					
					lastDestination = nextDestination;
					if(!selectedPlaces.isEmpty()){
						nextDestination = locationOfPlaces.get(selectedPlaces.get(0));
					}
				}
			} else {
				progress = 4;
			}
		} else {
			progress = (int) ((100*distanceDone/(distanceTotal*25)));
		}
		
		if(progress > currentProgress){
			currentProgress++;
			if(currentProgress == 5){
				currentProgress= 0;
			}
			GBike.communicator.sendBTMsg("s");
		} else if (progress < currentProgress && currentProgress>0){
			currentProgress--;
			GBike.communicator.sendBTMsg("a");
		}
		GBike.communicator.sendBTMsg(String.valueOf(progress));
		updateMyLocation();
		if(distanceTotal+20< distancePending){
			 updateRoute();
		}
		newDirection.LatA = gpsLocation.getLatitude();
		newDirection.LongA = gpsLocation.getLongitude();
		newDirection.LatB = nextDestination.getLatitudeE6()/ 1E6;
		newDirection.LongB = nextDestination.getLongitudeE6()/ 1E6;
		newDirection.LatC = lastDestination.getLatitudeE6()/ 1E6;
		newDirection.LongC = lastDestination.getLongitudeE6()/ 1E6;
		newDirection.UpdateMethod();
		
		Log.e("step",String.valueOf(newDirection.directionIHaveToFollow) + " " + String.valueOf(progress));
		GBike.communicator.sendBTMsg("" + directionOrders[newDirection.directionIHaveToFollow-1]);
	}
	private void fullLocationsOfPlaces() {

		GeoPoint aux;
		locationOfPlaces = new HashMap<String, GeoPoint>();
		locationInverse = new HashMap<GeoPoint, String>();
		iconsOfPlaces = new HashMap<String, Drawable>();
		selectedPlaces = RouteSelector.listStops;

		aux = new GeoPoint(
				(int) (52.359933 * 1E6), ((int) (4.884418 * 1E6)));
		locationOfPlaces.put("Rijksmuseum", aux);
		locationInverse.put(aux,"Rijksmuseum");
		
		aux =  new GeoPoint(
				(int) (52.376071 * 1E6), ((int) (4.883938 * 1E6)));
		locationOfPlaces.put("Anne frank museum",aux);
		locationInverse.put(aux,"Anne frank museum");
		
		aux = new GeoPoint(
				(int) (52.378979 * 1E6), ((int) (4.900632 * 1E6)));		
		locationOfPlaces.put("Central Station",aux );
		locationInverse.put(aux,"Central Station");
		
		aux =  new GeoPoint((int) (52.374577 * 1E6),
				((int) (4.888959 * 1E6)));
		locationOfPlaces.put("Flower Market",aux);
		locationInverse.put(aux,"Flower Market");
		
		aux = new GeoPoint(
				(int) (52.374047 * 1E6), ((int) (4.895214 * 1E6)));
		locationOfPlaces.put("Damsquare",aux );
		locationInverse.put(aux,"Damsquare");
		
		aux = new GeoPoint(
				(int) (52.357479 * 1E6), ((int) (4.880065 * 1E6)));
		locationOfPlaces.put("Stedelijk",aux );
		locationInverse.put(aux,"Stedelijk");
		
		aux = new GeoPoint(
				(int) (52.35815 * 1E6), ((int) (4.881451 * 1E6)));
		locationOfPlaces.put("Van Gogh",aux );
		locationInverse.put(aux,"Van Gogh");
		aux = new GeoPoint(
				(int) (52.36531 * 1E6), ((int) (4.902503 * 1E6)));
		locationOfPlaces.put("Hermitage",aux );
		locationInverse.put(aux,"Hermitage");
		aux = new GeoPoint(
				(int) (52.371443 * 1E6), ((int) (4.915049 * 1E6)));
		locationOfPlaces.put("Scheepvaart",aux );
		locationInverse.put(aux,"Scheepvaart");
		aux = new GeoPoint(
				(int) (52.374332 * 1E6), ((int) (4.897301 * 1E6)));
		locationOfPlaces.put("Oude Kerk",aux );
		locationInverse.put(aux,"Oude Kerk");
		aux = new GeoPoint(
				(int) (52.358528 * 1E6), ((int) (4.869938 * 1E6)));
		locationOfPlaces.put("Vondelpark",aux );
		locationInverse.put(aux,"Vondelpark");
		aux = new GeoPoint(
				(int) (52.365143 * 1E6), ((int) (4.884622 * 1E6)));
		locationOfPlaces.put("Leidseplein",aux );
		locationInverse.put(aux,"Leidseplein");
		aux = new GeoPoint(
				(int) (52.369331 * 1E6), ((int) (4.88933 * 1E6)));
		locationOfPlaces.put("Spui",aux );
		locationInverse.put(aux,"Spui");
		aux = new GeoPoint(
				(int) (52.313988 * 1E6), ((int) (4.830315 * 1E6)));
		locationOfPlaces.put("Amsterdamse Bos",aux );
		locationInverse.put(aux,"Amsterdamse Bos");
		

		
		
		iconsOfPlaces.put("Rijksmuseum",
				this.getResources().getDrawable(R.drawable.artmuseum));
		iconsOfPlaces.put("Anne frank museum",
				this.getResources().getDrawable(R.drawable.house));
		iconsOfPlaces.put("Central Station",
				this.getResources().getDrawable(R.drawable.train));
		iconsOfPlaces.put("Damsquare",
				this.getResources().getDrawable(R.drawable.bigcity));
		iconsOfPlaces.put("Flower Market",
				this.getResources().getDrawable(R.drawable.flowers));
		iconsOfPlaces.put("mylocation",
				this.getResources().getDrawable(R.drawable.mylocation));

		
		iconsOfPlaces.put("Stedelijk",
				this.getResources().getDrawable(R.drawable.abduction));
		iconsOfPlaces.put("Van Gogh",
				this.getResources().getDrawable(R.drawable.wetlands));
		iconsOfPlaces.put("Hermitage",
				this.getResources().getDrawable(R.drawable.officebuilding));
		iconsOfPlaces.put("Scheepvaart",
				this.getResources().getDrawable(R.drawable.museumnaval));
		iconsOfPlaces.put("Oude Kerk",
				this.getResources().getDrawable(R.drawable.cross2));
		iconsOfPlaces.put("Vondelpark",
				this.getResources().getDrawable(R.drawable.grass));
		iconsOfPlaces.put("Leidseplein",
				this.getResources().getDrawable(R.drawable.musicrock));
		iconsOfPlaces.put("Spui",
				this.getResources().getDrawable(R.drawable.aboriginal));
		iconsOfPlaces.put("Amsterdamse Bos",
				this.getResources().getDrawable(R.drawable.forest2));
		Log.e("LOCATIONSandICONS", "ADDED ALL");

	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.map);

		fullLocationsOfPlaces();
		// ADD ZOOM BUTTONS
		mapView = (MapView) findViewById(R.id.mapView);
		mapView.setBuiltInZoomControls(true);

		// SET VIEW LOCATION
		MapController mc = mapView.getController();
		double lat = Double.parseDouble("52.378588"); // latitude
		double lon = Double.parseDouble("4.900439"); // longitude
		GeoPoint geoPoint = new GeoPoint((int) (lat * 1E6), (int) (lon * 1E6));
		mc.animateTo(geoPoint);
		mc.setZoom(14);
		mapView.invalidate();

		// SET MARKS

		GPSStore.setMapsActivity(this);
		updateRoute();

	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	public void onDirectionsAvailable(RouteAbstract route, Mode mode) {
		Log.e("Directions", "Available " + route.getGeoPointPath(RoutePathSmoothness.FINE).size());
		// Add a directions overlay to the map.
		// This is just a quick example to draw the line on the map.
		DirectionsOverlay directions = new DirectionsOverlay();
		directions.setRoute((DirectionsAPIRoute) route);
	

		mapView.getOverlays().add(directions);
		mapView.requestLayout();
		Toast.makeText(this, "Route done! Zoom in!", Toast.LENGTH_LONG).show();

	}

	public void updateRoute() {
		Log.e("MAP", "Updating route");
		List<GeoPoint> waypoints = new ArrayList<GeoPoint>();
		List<Overlay> mapOverlays = mapView.getOverlays();
		mapOverlays.clear();
		if (showLocationToast == true && showedLocationToast == false) {
			showedLocationToast = true;
			Toast.makeText(this, "GPS Connection done", Toast.LENGTH_LONG)
					.show();
			lastDestination = new GeoPoint(
					(int) (gpsLocation.getLatitude() * 1E6),
					(int) (gpsLocation.getLongitude() * 1E6));
			
			nextDestination = locationOfPlaces.get(selectedPlaces.get(0));

		}

		if (isLocationAvaliable) {
			GeoPoint myLocation = new GeoPoint(
					(int) (gpsLocation.getLatitude() * 1E6),
					(int) (gpsLocation.getLongitude() * 1E6));
			Drawable icon = iconsOfPlaces.get("mylocation");
			myLocationOverlay = new AddItemizedOverlay(icon, this);
			OverlayItem itemOverlay = new OverlayItem(myLocation, "You",
					"Your position");
			myLocationOverlay.addOverlay(itemOverlay);
			mapOverlays.add(myLocationOverlay);
			waypoints.add(myLocation);
		}

		for (String location : selectedPlaces) {
			Log.e("MAP", "Adding " + location);
			GeoPoint coordinates = locationOfPlaces.get(location);
			Log.e("MAP", "coordinates:");
			Log.e("MAP", coordinates.toString());
			Log.e("MAP", "requesting icon:");
			Drawable icon = iconsOfPlaces.get(location);
			Log.e("MAP", icon.toString());
			AddItemizedOverlay addItemOverlay = new AddItemizedOverlay(icon,
					this);
			OverlayItem itemOverlay = new OverlayItem(coordinates, location,
					location);
			addItemOverlay.addOverlay(itemOverlay);
			mapOverlays.add(addItemOverlay);
			Log.e("MAP", "Added overlay");
			Log.e("MAP", "adding coordinates to the routing");
			waypoints.add(coordinates);
		}

		Log.e("waypoints", String.valueOf(waypoints.size()));

		if (waypoints.size() > 1) {
			Toast.makeText(this, "Calculating route...", Toast.LENGTH_LONG)
					.show();
			DirectionsAPI directions = new DirectionsAPI();
			directions.getDirectionsThruWaypoints(waypoints,
					DirectionsAPI.Mode.BICYCLING, this);

		} else {
			Toast.makeText(this, "Waiting for your location...",
					Toast.LENGTH_LONG).show();
		}
		
		mapView.invalidate();
	}

	@Override
	public void onDirectionsNotAvailable() {
		Log.e("Directions", "NOT available");
		Toast.makeText(this, "Google is not responding", Toast.LENGTH_LONG)
				.show();
		Toast.makeText(this, "Check your data connection", Toast.LENGTH_LONG)
				.show();
	}

	public class DirectionsOverlay extends Overlay {

		static final String TAG = "DirectionsOverlay";

		// The route to draw
		private DirectionsAPIRoute mRoute;

		// Our Paint
		Paint pathPaint = new Paint();

		public DirectionsOverlay() {
			this.pathPaint.setAntiAlias(true);
		}

		public DirectionsOverlay setRoute(DirectionsAPIRoute route) {
			this.mRoute = route;
			return this;
		}

		// This function does some fancy drawing
		public void draw(android.graphics.Canvas canvas, MapView mapView,
				boolean shadow) {

			// This method will be called twice. Once in the
			// shadow phase, skewed and darkened, then again in
			// the non-shadow phase.

			if (this.mRoute != null && !shadow) {

				Path thePath = new Path();

				/* Reset our paint. */
				this.pathPaint.setStrokeWidth(3);
				this.pathPaint.setARGB(200, 255, 0, 0);
				// holders of mapped coords...
				Point screen = new Point();

				/*
				 * This drawing code needs some work to filter the path to the
				 * portion that is on the screen. The FINE line really slows
				 * things down
				 */

				RoutePathSmoothness smoothenss = (mapView.getZoomLevel() < 5) ? RoutePathSmoothness.ROUGH
						: RoutePathSmoothness.FINE;
				List<GeoPoint> drawPoints = mRoute.getGeoPointPath(smoothenss);

				Iterator<GeoPoint> itr = drawPoints.listIterator();

				if (itr.hasNext()) {
					// convert the start point.
					mapView.getProjection().toPixels((GeoPoint) itr.next(),
							screen);
					thePath.moveTo(screen.x, screen.y);

					while (itr.hasNext()) {
						GeoPoint p = (GeoPoint) itr.next();
						mapView.getProjection().toPixels(p, screen);
						thePath.lineTo(screen.x, screen.y);
					}

					this.pathPaint.setStyle(Paint.Style.STROKE);
					canvas.drawPath(thePath, this.pathPaint);
				}

			}

			super.draw(canvas, mapView, shadow);

		}

	}

	private void updateMyLocation() {
		Log.e("MAP", "On update my location");
		if (myLocationOverlay != null) {
			Log.e("MAP", "Updating GPS overlay");
			mapView.getOverlays().remove(myLocationOverlay);
			GeoPoint myLocation = new GeoPoint(
					(int) (gpsLocation.getLatitude() * 1E6),
					(int) (gpsLocation.getLongitude() * 1E6));
			Drawable icon = iconsOfPlaces.get("mylocation");
			myLocationOverlay = new AddItemizedOverlay(icon, this);
			OverlayItem itemOverlay = new OverlayItem(myLocation, "You",
					"Your position");
			myLocationOverlay.addOverlay(itemOverlay);
			mapView.getOverlays().add(myLocationOverlay);
			mapView.invalidate();
		}

	}

}